package wox.lonice.aop.impl;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import wox.lonice.aop.IAop;

/**
 * service层AOP编程
 * @author jh
 * JoinPoint.getArgs()//当前入参
 *
 */
@Aspect
@Component
public class AopService implements IAop{
    
	/**
	 * 当前方法的类属性
	 * 可以获取当前类，当前方法
	 */
    private Signature signature;
    
    private String classMethod;
    
    /**
     * 前置通知：目标方法执行之前执行以下方法体的内容 
     * @param jp
     */
    @Before("execution(* wox.lonice.service.*.*(..))")
    @Override
    public void beforeMethod(JoinPoint jp){
        this.setSignature(jp.getSignature());
        this.setClassMethod("[AOP]" + signature.getDeclaringTypeName() + "." + signature.getName() + " - ");
        System.out.println("【前置通知】" + classMethod + Arrays.asList(jp.getArgs()));
    }

    /**
     * 返回通知：目标方法正常执行完毕时执行以下代码
     * @param jp
     * @param result
     */
    @AfterReturning(value="execution(* wox.lonice.service.*.*(..))",returning="result")
    @Override
    public void afterReturningMethod(JoinPoint jp, Object result){
        System.out.println("【返回通知】" + classMethod + result);
    }

    /**
     * 后置通知：目标方法执行之后执行以下方法体的内容，不管是否发生异常。
     * 类似于try中 finally
     * @param jp
     */
    @After("execution(* wox.lonice.service.*.*(..))")
    @Override
    public void afterMethod(JoinPoint jp){
        System.out.println("【后置通知】this is a afterMethod advice...");
    }

    /**
     * 异常通知：目标方法发生异常的时候执行以下代码
     */
    @AfterThrowing(value="execution(* wox.lonice.service.*.*(..))",throwing="e")
    @Override
    public void afterThorwingMethod(JoinPoint jp, NullPointerException e){
        System.out.println("【异常通知】" + classMethod + " exception: " + e);
    }

    /**
     * 环绕通知：目标方法执行前后分别执行一些代码，发生异常的时候执行另外一些代码
     * @return 
     */
//    @Around(value="execution(* wox.lonice.service.*.*(..))")
    @Override
    public Object aroundMethod(ProceedingJoinPoint jp){
        String methodName = jp.getSignature().getName();
        Object result = null;
        try {
            System.out.println("【环绕通知中的--->前置通知】：the method 【" + methodName + "】 begins with " + Arrays.asList(jp.getArgs()));
            //执行目标方法
            result = jp.proceed();
            System.out.println("【环绕通知中的--->返回通知】：the method 【" + methodName + "】 ends with " + result);
        } catch (Throwable e) {
            System.out.println("【环绕通知中的--->异常通知】：the method 【" + methodName + "】 occurs exception " + e);
        }
        System.out.println("【环绕通知中的--->后置通知】：-----------------end.----------------------");
        return result;
    }

	private void setSignature(Signature signature) {
		this.signature = signature;
	}

	private void setClassMethod(String classMethod) {
		this.classMethod = classMethod;
	}

}
